package com.xjy.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjy.common.core.mybatisplus.core.ServicePlusImpl;
import com.xjy.common.core.page.PagePlus;
import com.xjy.common.core.page.TableDataInfo;
import com.xjy.common.exception.CustomException;
import com.xjy.common.exception.UtilException;
import com.xjy.common.utils.PageUtils;
import com.xjy.system.domain.SysCreditAdvance;
import com.xjy.system.domain.SysDeposit;
import com.xjy.system.domain.bo.*;
import com.xjy.system.domain.vo.SysCreditAdvanceVo;
import com.xjy.system.domain.vo.SysDepositVo;
import com.xjy.system.domain.vo.SysMaterialMngVo;
import com.xjy.system.mapper.SysCreditAdvanceMapper;
import com.xjy.system.service.ISysCheckaccountService;
import com.xjy.system.service.ISysCreditAdvanceService;
import com.xjy.system.service.ISysFundaccountdetailService;
import com.xjy.system.service.ISysImageMngService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 预付账款信息Service业务层处理
 *
 * @author xjy
 * @date 2022-02-10
 */
@Service
public class SysCreditAdvanceServiceImpl extends ServicePlusImpl<SysCreditAdvanceMapper, SysCreditAdvance> implements ISysCreditAdvanceService {

	@Autowired
	private ISysFundaccountdetailService iSysFundaccountdetailService;

	@Autowired
	private ISysCheckaccountService iSysCheckaccountService;

	@Autowired
	private ISysImageMngService iSysImageMngService;


	@Override
	public SysCreditAdvanceVo queryById(Long id) {
		return getVoById(id, SysCreditAdvanceVo.class);
	}

	@Override
	public TableDataInfo<SysCreditAdvanceVo> queryPageList(SysCreditAdvanceQueryBo bo) {
		List<SysCreditAdvanceVo> sysMaterialMngVoList = baseMapper.queryList(bo);
		return PageUtils.getPageInfo(sysMaterialMngVoList);

	}

	@Override
	public List<SysCreditAdvanceVo> queryList(SysCreditAdvanceQueryBo bo) {
		return listVo(buildQueryWrapper(bo), SysCreditAdvanceVo.class);
	}
	@Override
	public List<SysCreditAdvanceVo> querySelectList( ) {
		return baseMapper.querySelectList();
	}
	private LambdaQueryWrapper<SysCreditAdvance> buildQueryWrapper(SysCreditAdvanceQueryBo bo) {
		Map<String, Object> params = bo.getParams();
		LambdaQueryWrapper<SysCreditAdvance> lqw = Wrappers.lambdaQuery();
		lqw.eq(bo.getProjId() != null, SysCreditAdvance::getProjId, bo.getProjId());
		lqw.eq(bo.getContractId() != null, SysCreditAdvance::getContractId, bo.getContractId());
		lqw.eq(bo.getResultProjId() != null, SysCreditAdvance::getResultProjId, bo.getResultProjId());
		lqw.eq(bo.getBudgetId() != null, SysCreditAdvance::getBudgetId, bo.getBudgetId());
		lqw.eq(StrUtil.isNotBlank(bo.getAdvanceNo()), SysCreditAdvance::getAdvanceNo, bo.getAdvanceNo());
		lqw.eq(StrUtil.isNotBlank(bo.getAdvanceNoBack()), SysCreditAdvance::getAdvanceNoBack, bo.getAdvanceNoBack());
		lqw.eq(bo.getAdvanceType() != null, SysCreditAdvance::getAdvanceType, bo.getAdvanceType());
		lqw.eq(StrUtil.isNotBlank(bo.getAdvancePayer()), SysCreditAdvance::getAdvancePayer, bo.getAdvancePayer());
		lqw.eq(bo.getAdvancePayId() != null, SysCreditAdvance::getAdvancePayId, bo.getAdvancePayId());
		lqw.eq(StrUtil.isNotBlank(bo.getAdvanceNoCharge()), SysCreditAdvance::getAdvanceNoCharge, bo.getAdvanceNoCharge());
		lqw.eq(StrUtil.isNotBlank(bo.getAdvanceColer()), SysCreditAdvance::getAdvanceColer, bo.getAdvanceColer());
		lqw.eq(bo.getAdvanceColId() != null, SysCreditAdvance::getAdvanceColId, bo.getAdvanceColId());
		lqw.eq(bo.getAdvanceAmt() != null, SysCreditAdvance::getAdvanceAmt, bo.getAdvanceAmt());
		lqw.eq(bo.getAdvanceOpenTime() != null, SysCreditAdvance::getAdvanceOpenTime, bo.getAdvanceOpenTime());
		lqw.eq(bo.getAdvanceBalance() != null, SysCreditAdvance::getAdvanceBalance, bo.getAdvanceBalance());
		lqw.eq(bo.getWriteoffStatus() != null, SysCreditAdvance::getWriteoffStatus, bo.getWriteoffStatus());
		lqw.eq(StrUtil.isNotBlank(bo.getHandler()), SysCreditAdvance::getHandler, bo.getHandler());
		lqw.eq(bo.getHandlerId() != null, SysCreditAdvance::getHandlerId, bo.getHandlerId());
		lqw.eq(StrUtil.isNotBlank(bo.getColBank()), SysCreditAdvance::getColBank, bo.getColBank());
		lqw.eq(bo.getPayType() != null, SysCreditAdvance::getPayType, bo.getPayType());
		lqw.eq(StrUtil.isNotBlank(bo.getColBankNo()), SysCreditAdvance::getColBankNo, bo.getColBankNo());
		lqw.eq(bo.getPayAccountId() != null, SysCreditAdvance::getPayAccountId, bo.getPayAccountId());
		lqw.eq(StrUtil.isNotBlank(bo.getPayAccountBank()), SysCreditAdvance::getPayAccountBank, bo.getPayAccountBank());
		lqw.eq(StrUtil.isNotBlank(bo.getPayAccountNo()), SysCreditAdvance::getPayAccountNo, bo.getPayAccountNo());
		lqw.eq(bo.getAuditStatus() != null, SysCreditAdvance::getAuditStatus, bo.getAuditStatus());
		lqw.in(null != bo.getIdList() && bo.getIdList().size() > 0,SysCreditAdvance::getId,bo.getIdList());

		return lqw;
	}

	@Override
	public Boolean insertByAddBo(SysCreditAdvanceAddBo bo) {
		SysCreditAdvance add = BeanUtil.toBean(bo, SysCreditAdvance.class);

		validEntityBeforeSave(add);
		return save(add);
	}

	@Override
	public Boolean updateByEditBo(SysCreditAdvanceEditBo bo) {
		SysCreditAdvance update = BeanUtil.toBean(bo, SysCreditAdvance.class);

		validEntityBeforeSave(update);
		return updateById(update);
	}

	@Transactional
	@Override
    public synchronized Boolean  auditByEditBo(BaseAuditBo req) {

		boolean rsp = false;
		List<Long> idList = req.getIdList();
		if(null == idList || idList.size() == 0){
			throw new CustomException("需审核的数据不能为空！");
		}

		SysCreditAdvanceQueryBo sysCreditAdvanceQueryBo = new SysCreditAdvanceQueryBo();
		sysCreditAdvanceQueryBo.setIdList(idList);
		sysCreditAdvanceQueryBo.setAuditStatus(false);
		List<SysCreditAdvanceVo> sysCreditAdvanceVoList = this.queryList(sysCreditAdvanceQueryBo);
		if(null == sysCreditAdvanceVoList || sysCreditAdvanceVoList.size() == 0){
			throw new CustomException("勾选的数据审核状态已审批，无需重新审批！");
		}
		for(SysCreditAdvanceVo sysCreditAdvanceVo:sysCreditAdvanceVoList){
			// TODO 结账效验
			iSysCheckaccountService.check(sysCreditAdvanceVo.getProjId(),sysCreditAdvanceVo.getAdvanceOpenTime());
			SysCreditAdvance updateOne = new SysCreditAdvance();
			updateOne.setId(sysCreditAdvanceVo.getId());

			String advanceNo = sysCreditAdvanceVo.getAdvanceNo();
			Integer advanceType = sysCreditAdvanceVo.getAdvanceType();
			BigDecimal advanceAmt = sysCreditAdvanceVo.getAdvanceAmt();
			if(advanceAmt.compareTo(new BigDecimal(0)) <= 0){
				throw new UtilException("发生金额必须大于0！");
			}
			BigDecimal advanceBalance = null;
			//预付账款类别0：协议支付，1：预付退回
			if(advanceType.equals(0)){
				advanceBalance = advanceAmt;
			}

			if(advanceType.equals(1)){
				SysCreditAdvanceQueryBo sysCreditAdvanceQueryBoReq = new SysCreditAdvanceQueryBo();
				sysCreditAdvanceQueryBoReq.setAdvanceNo(advanceNo);
				sysCreditAdvanceQueryBo.setAdvanceType(0);
				sysCreditAdvanceQueryBoReq.setAuditStatus(true);
				List<SysCreditAdvanceVo> list = this.queryList(sysCreditAdvanceQueryBoReq);
				if(null == list || list.size() == 0){
					throw new UtilException("预付退回,未查询到对应预付款支付单！");
				}
				SysCreditAdvanceVo payInfo = list.get(0);
				if(payInfo.getWriteoffStatus().equals(1)){
					throw new UtilException("预付退回,预付款单已是冲销状态！");

				}
				SysCreditAdvance updatePay = new SysCreditAdvance();
				BigDecimal advanceBalanceNow = payInfo.getAdvanceBalance();
				if(advanceBalanceNow.compareTo(advanceAmt) == -1){
					throw new UtilException("预付退回金额不能大于余额！");
				}
				//计算余额
				BigDecimal advanceBalanceNew = advanceBalanceNow.subtract(advanceAmt);
				if(advanceBalanceNew.compareTo(new BigDecimal(0)) == 0){
					//已冲销
					updatePay.setWriteoffStatus(1);
				}
				updatePay.setId(payInfo.getId());
				updatePay.setAdvanceBalance(advanceBalanceNew);
				baseMapper.updateById(updatePay);

			}
			updateOne.setAdvanceBalance(advanceBalance);
			boolean changeFundaccount = this.changeFundaccount(sysCreditAdvanceVo);
			if(!changeFundaccount){
				throw new CustomException("更新资金流水失败！");
			}

			if(sysCreditAdvanceVo.getAdvanceType() == 0){
				this.uploadImage(sysCreditAdvanceVo);

			}
			updateOne.setAuditStatus(true);
			rsp = baseMapper.updateById(updateOne) > 0;
		}

		return rsp;
	}


	private synchronized Boolean changeFundaccount(SysCreditAdvanceVo req){
		Integer advanceType = req.getAdvanceType();
		//预付款冲销2报错
		if (advanceType.equals(2)) {
			throw new CustomException("预付款冲销数据，无须手动审核！");

		}
		SysFundaccountdetailAddBo addBo = new SysFundaccountdetailAddBo();

		//1：预付退回+
		if (advanceType.equals(1)) {
			addBo.setCategory(0L);
		}
		//预付账款类别0：协议支付-
		if (advanceType.equals(0)) {
			addBo.setCategory(1L);


		}
		addBo.setProjId(req.getProjId());
		addBo.setProjName(req.getProjName());
		addBo.setSubjectId(req.getBudgetId());
		addBo.setSubjectName(req.getBudgetName());
		addBo.setContractId(req.getContractId());
		addBo.setContractName(req.getContractName());
		addBo.setSettleProj(req.getResultProjId());
		addBo.setSettleProjName(req.getResultProjName());

		addBo.setAccId(req.getPayAccountId());
		addBo.setAccountName(req.getPayAccountName());
		addBo.setAccountBank(req.getPayAccountBank());
		addBo.setAccountNo(req.getPayAccountNo());
		//0：协议支付-，1：预付退回+
		if(advanceType.equals(0)){
			addBo.setTransactionId(req.getAdvanceNo());
			addBo.setTransactionCategory(2L);
		}else {
			addBo.setTransactionId(req.getAdvanceNoBack());
			addBo.setTransactionCategory(2L);
		}
		addBo.setSenderId(req.getAdvancePayId());
		addBo.setSender(req.getAdvancePayer());
		addBo.setReceiveId(req.getAdvanceColId());
		addBo.setReceive(req.getAdvanceColer());
		addBo.setManagerId(req.getHandlerId());
		addBo.setManager(req.getHandler());
		addBo.setTransactionType(req.getPayType());

		addBo.setTransactionDate(req.getAdvanceOpenTime());
		addBo.setAmount(req.getAdvanceAmt());
		addBo.setRemarks(req.getRemark());
		return iSysFundaccountdetailService.insertByAddBo(addBo);
	}


	private boolean uploadImage(SysCreditAdvanceVo req){
		boolean rsp = false;
		if(StringUtils.isNotBlank(req.getImage()) && !"[]".equals(req.getImage())){
			SysImageMngAddBo sysImageMngAddBo = new SysImageMngAddBo();
			sysImageMngAddBo.setAuditStatus(true);
			sysImageMngAddBo.setProjId(req.getProjId());
			sysImageMngAddBo.setImage(req.getImage());
			sysImageMngAddBo.setType(3+"");
			sysImageMngAddBo.setOperatorId(req.getHandlerId());
			sysImageMngAddBo.setOperator(req.getHandler());
			sysImageMngAddBo.setOutNo(req.getAdvanceNo());
			rsp = iSysImageMngService.insertByAddBo(sysImageMngAddBo);

		}

		return rsp;
	}
	public Boolean updateByBo(SysCreditAdvance update) {
		return updateById(update);
	}

	private void writeoffStatusCheck(SysCreditAdvance sysCreditAdvance) {

		if (sysCreditAdvance.getAdvanceType() == 0) {
			//预付支付
			return;
		}

		BigDecimal sumAmt = getBaseMapper().SumAmt(sysCreditAdvance.getAdvanceNo());
		SysCreditAdvance sysCreditAdvance1 = getBaseMapper().selectByAdvanceNo(sysCreditAdvance.getAdvanceNo());
		double res = sysCreditAdvance1.getAdvanceAmt().subtract(sumAmt).subtract(sysCreditAdvance.getAdvanceAmt()).doubleValue();
		if (res == 0) {
			sysCreditAdvance1.setWriteoffStatus(1);
			updateByBo(sysCreditAdvance1);
		} else if (res < 0) {
			throw new CustomException("退款金额超付");
		}


	}

	/**
	 * 保存前的数据校验
	 *
	 * @param entity 实体类数据
	 */
	private void validEntityBeforeSave(SysCreditAdvance entity) {
		// TODO 结账效验
		iSysCheckaccountService.check(entity.getProjId(),entity.getAdvanceOpenTime());
	}

	@Override
	public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
		if (isValid) {
			//TODO 做一些业务上的校验,判断是否需要校验
		}
		return removeByIds(ids);
	}
}
